package com.bac.rentmap.ad.crawler.stepped;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.JDomSerializer;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;
import org.jdom.Document;
import org.jdom.output.XMLOutputter;

import com.bac.rentmap.ad.crawler.CrawledAd;
import com.bac.rentmap.ad.crawler.support.CrawlingSupport;

/**
 * Contains utility methods for ad crawling.
 * 
 * @author Andrew Osipenko
 */
public abstract class AbstractSteppedAdCrawler<T extends CrawledAd> extends
		CrawlingSupport<List<T>> implements SteppedAdCrawler<T> {
	private static final Logger log = Logger
			.getLogger(AbstractSteppedAdCrawler.class.getName());

	abstract protected String getItemXPath();

	final public List<T> crawlNext() throws IOException {
		return crawl(getNextUrl(), null);
	}

	protected List<T> parseRootTagNode(TagNode rootNode, List<T> source)
			throws XPatherException {
		Object[] objects = rootNode.evaluateXPath(getItemXPath());
		if (objects.length == 0) {
			logParseError(rootNode);
			throw new RuntimeException("Can't parse any items from " + rootNode);
		}
		List<T> res = new ArrayList<T>();
		log.fine("Parsing " + objects.length + " items");
		for (Object object : objects) {
			TagNode tagNode = (TagNode) object;
			try {
				T flatCrawledAd = parseCrawledAd(tagNode);
				log.fine("Parsed " + flatCrawledAd);
				res.add(flatCrawledAd);
			} catch (IllegalArgumentException e) {
				log.warning("Can't parse ad from " + tagNode.getText()
						+ " because " + e.getMessage());
			}
		}
		return res;
	}

	private void logParseError(TagNode rootNode) {
		CleanerProperties cleanerProperties = new CleanerProperties();
		cleanerProperties.setUseCdataForScriptAndStyle(false);
		Document jdom = new JDomSerializer(cleanerProperties)
				.createJDom(rootNode);
		XMLOutputter outputter = new XMLOutputter();
		try {
			outputter.output(jdom, System.out);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	abstract protected T parseCrawledAd(TagNode tagNode)
			throws XPatherException;

	abstract protected String getNextUrl();

}
